<template>
  <div v-if="isLoading" class="flex justify-center items-center min-h-screen">
    <div class="text-electric-400 text-lg">加载中...</div>
  </div>
  <div v-else-if="!policy || policy.error" class="flex flex-col justify-center items-center min-h-screen space-y-4">
    <div class="text-red-400 text-lg">政策详情加载失败</div>
    <div v-if="policy && policy.errorMessage" class="text-red-300 text-sm max-w-md text-center">
      {{ policy.errorMessage }}
    </div>
    <button @click="retryLoadPolicy" class="px-4 py-2 bg-electric-500 text-black rounded hover:bg-electric-400 transition">
      重新加载
    </button>
  </div>
  <div v-else-if="!policy.title" class="flex justify-center items-center min-h-screen">
    <div class="text-yellow-400 text-lg">政策数据不完整</div>
  </div>
  <div v-else :class="['p-6 mx-auto space-y-6 text-white transition-all duration-300', sidebarCollapsed ? 'max-w-7xl' : 'max-w-6xl']">
    <!-- 顶部操作栏 -->
    <div class="flex justify-between items-center mb-6">
      <button @click="$router.go(-1)"
        class="flex items-center px-4 py-2 bg-electric-500 text-primary rounded-md hover:bg-electric-400 transition">
        <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" viewBox="0 0 20 20" fill="currentColor">
          <path fill-rule="evenodd"
            d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z"
            clip-rule="evenodd" />
        </svg>
        返回
      </button>
    </div>

    <!-- 主体左右分栏 -->
    <div class="flex flex-col lg:flex-row gap-8 transition-all duration-300">
      <!-- 左侧：政策详情 -->
      <div :class="['min-w-0 space-y-6 bg-white/5 rounded-lg p-6 border border-white/10 shadow transition-all duration-300', sidebarCollapsed ? 'flex-1' : 'flex-1']">
        <h1 class="text-2xl font-bold mb-2">{{ policy.title || '无标题' }}</h1>
        <div class="text-sm text-white/70 space-y-1">
          <p>发文编号：{{ policy.symbol || policy.documentNumber || '-' }}</p>
          <p>发布部门：{{ policy.department || '-' }}</p>
          <p>成文时间：{{ formatDate(policy.write_time) }}</p>
          <p>发布时间：{{ formatDate(policy.publish_date) }}</p>
          <p>生效时间：{{ formatDate(policy.start_time) }}</p>
          <p>失效时间：{{ formatDate(policy.end_time) }}</p>
          <p>政策类型：{{ policy.type || '-' }}</p>
          <p>适用地区：{{ policy.address_2 || policy.address_1 || '-' }}</p>
          <p>政策级别：{{ policy.level || '-' }}</p>
          <p>语言：{{ policy.language || '-' }}</p>
          <p>是否有效：{{ policy.validity ? '有效' : '无效' }}</p>
          <p v-if="policy.link && policy.link !== 'null' && policy.link !== ''">
            政策链接：
            <a :href="policy.link" target="_blank" class="text-electric-400 hover:underline break-all">
              {{ policy.link }}
            </a>
          </p>
        </div>
        <div>
          <h2 class="text-xl font-semibold mb-2">政策原文</h2>
          <!-- 使用后端返回的字段 -->
          <pre class="whitespace-pre-wrap text-primary/90">{{ policy.mainText || policy.context || '暂无原文内容' }}</pre>
        </div>
      </div>
      <!-- 右侧：tab切换区 -->
      <div :class="['flex flex-col gap-4 transition-all duration-300', sidebarCollapsed ? 'flex-1' : 'w-full lg:w-96']">
        <div class="flex border-b border-electric-500/30 mb-2">
          <button v-for="tab in tabs" :key="tab.key" @click="activeTab = tab.key"
            :class="['px-4 py-2 text-sm font-bold transition', activeTab === tab.key ? 'text-electric-400 border-b-2 border-electric-400' : 'text-white/60 hover:text-electric-400']">
            {{ tab.label }}
          </button>
        </div>
        <div class="flex-1 min-h-[220px]">
          <div v-show="activeTab === 'overview'">
            <div class="bg-white/5 p-4 rounded-lg shadow-md border border-white/10">
              <h2 class="text-lg font-bold text-electric-400 mb-3 flex items-center gap-2">
                <svg class="w-5 h-5 text-electric-500 animate-spin-slow" fill="none" stroke="currentColor"
                  stroke-width="2" viewBox="0 0 24 24">
                  <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none" />
                  <path stroke="currentColor" stroke-width="4" d="M4 12a8 8 0 018-8v8z" />
                </svg>
                政策内容关键词词云
              </h2>
              <div ref="wordcloud"
                style="width:100%;height:200px;background:linear-gradient(135deg,#0ff2fa22,#1a2b4c44);border-radius:12px;box-shadow:0 4px 24px #00f5ff22;">
              </div>
              <!-- 新增：政策流程图 -->
              <div class="mt-4">
                <h2 class="text-lg font-bold text-electric-400 mb-2 flex items-center gap-2">
                  <svg class="w-5 h-5 text-electric-500" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
                    <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none" />
                    <path stroke="currentColor" stroke-width="4" d="M12 2v20M2 12h20" />
                  </svg>
                  政策办理流程图
                  <div class="ml-auto flex items-center gap-2">
                    <button v-if="flowchartRaw && !flowchartError" @click="openFlowchartFullScreen" 
                      class="px-2 py-1 rounded text-xs bg-blue-500/20 text-blue-400 hover:bg-blue-500/30 font-bold shadow">
                      查看大图
                    </button>
                    <button @click="generatePolicyFlowchart" :disabled="flowchartLoading"
                      class="px-2 py-1 rounded text-xs bg-electric-500/80 hover:bg-electric-500 text-black font-bold shadow animate-btn-glow">
                      {{ flowchartLoading ? 'AI生成中...' : 'AI自动生成流程' }}
                    </button>
                  </div>
                </h2>
                <div ref="flowchart" style="width:100%;height:340px;background:linear-gradient(135deg,#0ff2fa11,#1a2b4c22);border-radius:12px;"></div>
                <div v-if="flowchartError" class="text-red-400 text-xs mt-2">{{ flowchartError }}</div>
                <div v-if="flowchartRaw" class="mt-2">
                  <details>
                    <summary class="text-xs text-electric-400 cursor-pointer select-none">AI原始内容调试</summary>
                    <pre class="text-xs bg-gray-900 text-green-400 p-2 rounded mt-1 overflow-x-auto" style="max-height:220px;">{{ flowchartRaw }}</pre>
                  </details>
                </div>
              </div>
            </div>
          </div>
          <div v-show="activeTab === 'news'">
            <!-- 相关新闻 -->
            <div class="bg-white/5 p-4 rounded-lg shadow-md border border-white/10">
              <h2 class="text-lg font-bold text-electric-400 mb-3">相关新闻</h2>
              <div v-if="relatedNews.length > 0" class="space-y-3">
                <div v-for="news in relatedNews" :key="news.url"
                  class="bg-black/10 p-3 rounded hover:bg-white/10 transition">
                  <a :href="news.url" target="_blank" class="text-electric-500 hover:underline font-medium">
                    {{ news.title }}
                  </a>
                  <p v-if="news.publisher" class="text-xs text-white/60 mt-1">
                    <span>{{ news.publisher }}</span>
                  </p>
                </div>
              </div>
              <p v-else class="text-white/50 text-sm">暂无相关新闻。</p>
            </div>
          </div>
          <div v-show="activeTab === 'mindmap'">
            <!-- 脑图结构图切换（多维度适配） -->
            <div class="bg-white/5 p-4 rounded-lg shadow-md border border-white/10">
              <div class="flex items-center gap-4 mb-3">
                <h2 class="text-lg font-bold text-electric-400 flex items-center gap-2 mb-0">
                  <svg class="w-5 h-5 text-electric-500" fill="none" stroke="currentColor" stroke-width="2"
                    viewBox="0 0 24 24">
                    <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none" />
                    <path stroke="currentColor" stroke-width="4" d="M12 2v20M2 12h20" />
                  </svg>
                  政策结构图
                </h2>
                <div class="ml-auto flex items-center gap-2">
                  <button v-if="policyMindmap && policyMindmap.title" @click="openMindmapFullScreen" 
                    class="px-2 py-1 rounded text-xs bg-green-500/20 text-green-400 hover:bg-green-500/30 font-bold shadow">
                    查看大图
                  </button>
                  <button @click="generateAIMindmap" :disabled="aiMindmapLoading"
                    class="px-2 py-1 rounded text-xs bg-electric-500/80 hover:bg-electric-500 text-black font-bold shadow animate-btn-glow">
                    {{ aiMindmapLoading ? 'AI生成中...' : 'AI自动生成要点' }}
                  </button>
                </div>
              </div>
              <!-- 多维度tab -->
              <div class="flex gap-2 mb-2">
                <button v-for="dim in mindmapDimensions" :key="dim.key" @click="changeMindmapDimension(dim.key)"
                  :class="['px-3 py-1 rounded text-xs font-bold transition', mindmapDimension === dim.key ? 'bg-electric-500/80 text-black' : 'bg-white/10 text-electric-400 hover:bg-electric-500/30']">
                  {{ dim.label }}
                </button>
              </div>
              <div v-if="aiMindmapLoading" class="text-blue-400 py-4 text-center">脑图生成中...</div>
              <div v-if="mindmapError" class="text-red-400 py-4 text-center">{{ mindmapError }}</div>
              <MindmapGraph v-if="policyMindmap && policyMindmap.title && !aiMindmapLoading && !mindmapError" :mindmap="policyMindmap" :dimension="mindmapDimension" style="width:100%;height:420px;" />
              <div v-else-if="!aiMindmapLoading && !mindmapError" class="text-white/50 py-8 text-center">暂无结构数据</div>
            </div>
          </div>
          <div v-show="activeTab === 'ai'">
            <!-- 智能解读 -->
            <div class="bg-white/5 p-4 rounded-lg shadow-md border border-white/10">
              <h2 class="text-lg font-bold text-electric-400 mb-3 flex items-center gap-2">
                <svg class="w-5 h-5 text-electric-500 animate-spin-slow" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
                  <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none" />
                  <path stroke="currentColor" stroke-width="4" d="M4 12a8 8 0 018-8v8z" />
                </svg>
                AI智能解读
                <button @click="analyzeWithDeepseek" :disabled="deepseekLoading" class="ml-auto px-2 py-1 rounded text-xs bg-electric-500/80 hover:bg-electric-500 text-black font-bold shadow animate-btn-glow">
                  {{ deepseekLoading ? 'AI解读中...' : '一键智能解读' }}
                </button>
              </h2>
              <div class="min-h-[120px] text-white/90 text-sm whitespace-pre-line break-words">
                <template v-if="deepseekLoading">
                  <span class="text-electric-400 animate-pulse">AI智能解读中，请稍候...</span>
                </template>
                <template v-else-if="deepseekResult">
                  <div class="flex items-center mb-2 gap-2">
                    <button @click="copyDeepseekResult" class="px-2 py-1 text-xs bg-blue-500/20 text-blue-400 rounded hover:bg-blue-500/30">复制</button>
                    <button @click="exportDeepseekResult" class="px-2 py-1 text-xs bg-green-500/20 text-green-400 rounded hover:bg-green-500/30">导出</button>
                  </div>
                  <div>{{ deepseekResult }}</div>
                </template>
                <template v-else-if="deepseekError">
                  <span class="text-red-400">{{ deepseekError }}</span>
                </template>
                <template v-else>
                  <span class="text-white/50">点击上方按钮，AI将自动解读政策原文要点。</span>
                </template>
              </div>
            </div>
          </div>
          <div v-show="activeTab === 'related'">
            <!-- 相关政策 -->
            <div class="bg-white/5 p-4 rounded-lg shadow-md border border-white/10">
              <h2 class="text-lg font-bold text-electric-400 mb-3">相关政策</h2>
              <div v-if="relatedPolicies.length > 0" class="space-y-3 max-h-72 overflow-y-auto relative">
                <div v-for="item in relatedPolicies" :key="item.id"
                  class="bg-black/10 p-3 rounded hover:bg-white/10 transition relative"
                  style="cursor:pointer">
                  <router-link :to="{ name: 'PolicyDetail', params: { id: item.id } }"
                    class="text-electric-500 hover:underline font-medium">
                    {{ item.title }}
                  </router-link>
                  <p class="text-xs text-white/60 mt-1">
                    {{ item.department }} · {{ item.publish_date }}
                  </p>
                </div>
              </div>
              <p v-else class="text-white/50 text-sm">暂无相关政策。</p>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 侧边滑出的图表显示组件 -->
    <SlideGraphModal
      v-if="showSlideGraph"
      :visible="showSlideGraph"
      :type="slideGraphType"
      :data="slideGraphData"
      :policy-title="policy.title"
      :dimension="mindmapDimension"
      @close="closeSlideGraph"
    />

  </div>
</template>


<script>
import * as d3 from 'd3';
import axios from 'axios';
import * as echarts from 'echarts';
import 'echarts-wordcloud/dist/echarts-wordcloud.min.js'
import MindmapGraph from '@/components/MindmapGraph.vue';
import SlideGraphModal from '@/components/SlideGraphModal.vue';
import PolicyWindow from '../components/PolicyWindow.vue'
import cloneDeep from 'lodash/cloneDeep';
import cytoscape from 'cytoscape';
import dagre from 'cytoscape-dagre';
cytoscape.use(dagre);

export default {
  name: 'PolicyDetail',
  data() {
    return {
      policy: {},
      relatedNews: [],
      relatedPolicies: [],
      tooltipPosition: { x: 0, y: 0 },
      isHoveringTooltip: false,
      showTooltip: false,
      tooltipHideTimer: null,
      deepseekLoading: false,
      deepseekResult: '',
      deepseekError: '',
      isLoading: true,
      directions: ['部门', '发布时间', '类型', '行业'],
      directionKeys: ['department', 'publish_date', 'type', 'industry_type_1'], // 对应字段
      policyMindmap: { title: '', children: [] },
      mindmapCollapse: {}, // 节点展开/收起状态
      activeMindmapNode: null, // 当前高亮节点
      aiMindmapLoading: false,
      mindmapDimension: 'theme', // 当前脑图维度，默认为主题维度
      mindmapDimensions: [
        { key: 'time', label: '时间维度' },
        { key: 'space', label: '空间维度' },
        { key: 'theme', label: '主题维度' }
      ],
      mindmapError: '',
      mindmapSimplified: true, // 简化模式开关
      mindmapShowLevel: 3, // 显示层级控制，默认3层
      flowchartData: null,
      flowchartRaw: '',
      flowchartLoading: false,
      flowchartError: '',
      tabs: [
        { key: 'overview', label: '总览' },
        { key: 'news', label: '相关新闻' },
        { key: 'related', label: '相关政策' },
        { key: 'mindmap', label: '脑图' },
        { key: 'ai', label: '智能解读' }
      ],
      activeTab: 'overview',
      showPolicyWindow: false,
      policyWindowData: null,
      policyWindowPosition: { x: 0, y: 0 },
      _policyWindowTimer: null,
      _isPolicyTitleHover: false,
      _isPolicyWindowHover: false,
      sidebarCollapsed: !!window.sidebarCollapsed,
      // 侧边滑出图表相关状态
      showSlideGraph: false,
      slideGraphType: '',
      slideGraphData: null,
    };
  },
  async created() {
    // 优化加载逻辑：主详情优先，其他异步
    console.log('PolicyDetail 组件被创建，路由参数：', this.$route.params);
    this.isLoading = true;
    const id = this.$route.params.id;
    try {
      if (id) {
        // 1. 只等待主政策详情
        await this.fetchPolicy(id);
      }
    } catch (error) {
      console.error("PolicyDetail 数据加载失败:", error);
      this.policy = null;
    } finally {
      this.isLoading = false;
    }

    // 2. 相关政策、相关新闻、词云、脑图等异步加载
    if (id) {
      // 相关政策
      axios.get(`/api/policy/related?id=${id}`)
        .then(res => { this.relatedPolicies = res.data || []; })
        .catch(err => { console.warn('获取相关政策失败：', err); this.relatedPolicies = []; });
    }
    // 相关新闻
    this.loadRelatedNews();
    // 词云
    this.$nextTick(() => {
      setTimeout(() => { this.renderWordCloud(); }, 200);
    });
    // 脑图（可选：首次自动生成）
    // this.generateAIMindmap();
  },
  watch: {
    async '$route.params.id'(newId) {
      if (!newId) return;
      this.isLoading = true;
      this.policyMindmap = { title: '', children: [] };
      this.deepseekResult = '';
      this.deepseekError = '';
      this.relatedNews = [];
      this.relatedPolicies = [];
      try {
        await this.fetchPolicy(newId);
      } catch (error) {
        console.error("路由变化时数据加载失败:", error);
        this.policy = null;
      } finally {
        this.isLoading = false;
      }
      // 相关政策、相关新闻、词云异步加载
      if (newId) {
        axios.get(`/api/policy/related?id=${newId}`)
          .then(res => { this.relatedPolicies = res.data || []; })
          .catch(err => { console.warn('获取相关政策失败：', err); this.relatedPolicies = []; });
      }
      this.loadRelatedNews();
      this.$nextTick(() => {
        setTimeout(() => { this.renderWordCloud(); }, 200);
      });
      // this.generateAIMindmap();
    },

    async activeTab(val) {
      if (val === 'overview') {
        // 多次尝试，确保容器已渲染且有高度
        for (let i = 0; i < 5; i++) {
          await this.$nextTick();
          const container = this.$refs.wordcloud;
          if (container && container.offsetWidth > 0 && container.offsetHeight > 0) {
            break;
          }
          await new Promise(resolve => setTimeout(resolve, 100));
        }
        // 每次切换到overview都刷新词云 - 添加延迟确保容器稳定
        setTimeout(() => {
          this.renderWordCloud();
        }, 100);
      } else if (val === 'news') {
        // 切换到相关新闻tab时，若未加载则请求
        if (!this.relatedNews || this.relatedNews.length === 0) {
          this.loadRelatedNews();
        }
      }
    },
    sidebarCollapsed(val) {
      // sidebar折叠/展开时，延迟动画结束后resize词云
      this.$nextTick(() => {
        setTimeout(() => {
          if (this._wordcloudChart) {
            this._wordcloudChart.resize();
          }
        }, 300); // 与transition-all duration-300保持一致
      });
    }
  },
  components: {
    PolicyWindow,
    MindmapGraph,
    SlideGraphModal,
  },
  methods: {
    // 获取政策详情的方法
    async fetchPolicy(id) {
      console.log('开始获取政策详情，ID：', id);
      try {
        const detailRes = await axios.get(`/api/policy/${id}`);
        const data = detailRes.data || {};
        console.log('获取到的政策数据：', data);
        
        // 字段映射，兼容后端返回的字段名
        this.policy = {
          ...data,
          id: data.policyId || data.id,
          // 保留原始字段名以供模板使用
          mainText: data.mainText || data.context,
          context: data.mainText || data.context,
          write_time: data.writeTime || data.write_time,
          publish_time: data.publishTime || data.publish_time,
          publish_date: data.publishTime || data.publish_date || data.publish_time,
          start_time: data.startTime || data.start_time,
          end_time: data.endTime || data.end_time,
          symbol: data.documentNumber || data.symbol,
          documentNumber: data.documentNumber || data.symbol,
          address_1: data.address1 || data.address_1,
          address_2: data.address2 || data.address_2,
          // 确保所有模板中使用的字段都有值
          title: data.title || '',
          department: data.department || '',
          type: data.type || '',
          language: data.language || '',
          level: data.level || '',
          validity: data.validity,
          link: data.link || '',
        };
        
        console.log('处理后的政策数据：', this.policy);
        return this.policy;
      } catch (error) {
        console.error('获取政策详情失败：', error);
        // 显示更详细的错误信息
        if (error.response) {
          // 服务器返回了错误响应
          console.error('服务器错误响应:', error.response.status, error.response.data);
          this.policy = { 
            error: true, 
            errorMessage: `服务器错误 ${error.response.status}: ${error.response.data?.message || '政策详情获取失败'}` 
          };
        } else if (error.request) {
          // 请求已发出但没有收到响应
          console.error('网络错误，无响应:', error.request);
          this.policy = { 
            error: true, 
            errorMessage: '网络连接失败，请检查网络连接或后端服务是否启动' 
          };
        } else {
          // 其他错误
          console.error('请求配置错误:', error.message);
          this.policy = { 
            error: true, 
            errorMessage: `请求错误: ${error.message}` 
          };
        }
        throw error;
      }
    },
    
    async loadRelatedNews() {
      try {
        const id = this.$route.params.id;
        // 记录当前请求的政策id
        this._lastNewsPolicyId = id;
        let params = { policyId: id };
        // 若有标题也一并传递，增强后端兼容性
        if (this.policy && this.policy.title) {
          params.title = this.policy.title;
        }
        if (id) {
          const newsRes = await axios.get('/api/news/related', { params });
          // 只在id未变化时才赋值，防止异步乱序
          if (this._lastNewsPolicyId === this.$route.params.id) {
            this.relatedNews = newsRes.data || [];
          }
        }
      } catch (e) {
        this.relatedNews = [];
      }
    },
    async renderWordCloud() {
    try {
      await this.$nextTick();
      
      // 多次尝试确保容器准备就绪
      let container = null;
      let attempts = 0;
      const maxAttempts = 10;
      
      while (attempts < maxAttempts) {
        container = this.$refs.wordcloud;
        if (container && container.offsetWidth > 0 && container.offsetHeight > 0) {
          break;
        }
        await new Promise(resolve => setTimeout(resolve, 100));
        attempts++;
      }
      
      if (!container) {
        console.warn('词云容器未找到');
        return;
      }
      
      const width = container.offsetWidth;
      const height = container.offsetHeight;
      
      if (!width || !height) {
        console.warn('词云容器尺寸无效:', { width, height });
        return;
      }
      
      console.log('词云容器尺寸:', { width, height });
      
      if (this._wordcloudChart) {
        this._wordcloudChart.dispose();
        this._wordcloudChart = null;
      }
      
      if (!this.policy || !this.policy.context) {
        console.warn('政策数据或内容为空');
        return;
      }
      
      // 由于后端更换，分词API可能不可用，使用简单的词频统计
      try {
        // const resp = await fetch('/api/ai/policy/segment', {
        //   method: 'POST',
        //   headers: { 'Content-Type': 'application/json' },
        //   body: JSON.stringify({ text: this.policy.context })
        // });
        
        // 简单的中文分词和词频统计
        const text = this.policy.context || '';
        const words = text.match(/[\u4e00-\u9fa5]{2,}/g) || []; // 提取2个字符以上的中文词汇
        const wordCount = {};
        
        words.forEach(word => {
          if (word.length >= 2 && word.length <= 6) { // 过滤合适长度的词
            wordCount[word] = (wordCount[word] || 0) + 1;
          }
        });
        
        const data = Object.entries(wordCount)
          .sort((a, b) => b[1] - a[1])
          .slice(0, 50)
          .map(([word, count]) => ({ name: word, value: count }));

        if (!data.length) return;
        
        this._wordcloudChart = echarts.init(container);
        this._wordcloudChart.setOption({
          tooltip: {
            show: true,
            formatter: function (params) {
              return `<b>${params.name}</b><br/>出现次数: <span style='color:#00f5ff'>${params.value}</span>`
            },
            backgroundColor: 'rgba(26, 37, 61, 0.95)',
            borderColor: '#00f5ff',
            textStyle: { color: '#fff', fontWeight: 'bold' }
          },
          series: [{
            type: 'wordCloud',
            gridSize: 8,
            sizeRange: [18, 54],
            rotationRange: [-30, 30],
            shape: 'diamond',
            width: '100%',
            height: '100%',
            textStyle: {
              fontFamily: 'PingFang SC, Microsoft YaHei, Arial',
              fontWeight: 'bold',
              color: function () {
                return `rgb(${Math.round(Math.random() * 100)},${Math.round(Math.random() * 255)},${Math.round(Math.random() * 255)})`
              },
              shadowColor: '#00f5ff',
              shadowBlur: 6
            },
            data,
            emphasis: {
              focus: 'self',
              textStyle: {
                fontSize: 60,
                color: '#00f5ff',
                shadowColor: '#00f5ff',
                shadowBlur: 16
              }
            },
            animation: true,
            animationDuration: 1200
          }]
        });
        
        window.addEventListener('resize', () => {
          if (this._wordcloudChart) this._wordcloudChart.resize();
        });
        
        console.log('词云渲染完成', data);
      } catch (e) {
        console.error('词云渲染异常', e);
      }
    } catch (e) {
      console.error('词云渲染异常', e);
    }
  },

    async analyzeWithDeepseek() {
    this.deepseekLoading = true;
    this.deepseekResult = '';
    this.deepseekError = '';
    try {
      if (!this.policy || !this.policy.id) {
        this.deepseekError = '政策数据不完整，无法进行AI解读';
        return;
      }

      console.log('开始AI智能解读，政策ID：', this.policy.id);
      
      // 调用后端AI智能解读接口
      const resp = await fetch(`/api/ai/policy/interpretById?id=${this.policy.id}`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json'
        }
      });
      
      if (!resp.ok) {
        throw new Error(`HTTP ${resp.status}: ${resp.statusText}`);
      }
      
      const result = await resp.json();
      console.log('AI解读接口返回：', result);
      
      if (result && result.aiSummary) {
        this.deepseekResult = result.aiSummary;
        this.deepseekError = '';
        console.log('AI解读成功');
      } else if (result && result.error) {
        this.deepseekError = result.error;
      } else {
        this.deepseekError = 'AI解读返回数据格式异常';
      }
      
    } catch (e) {
      console.error('AI智能解读失败：', e);
      this.deepseekError = e.message || '智能分析失败，请检查网络连接和后端服务';
    } finally {
      this.deepseekLoading = false;
    }
  },

    copyDeepseekResult() {
      if (!this.deepseekResult) return
      navigator.clipboard.writeText(this.deepseekResult)
        .then(() => {
          this.$toast?.success?.('内容已复制到剪贴板') || alert('内容已复制到剪贴板')
        })
        .catch(() => {
          this.$toast?.error?.('复制失败，请手动复制') || alert('复制失败，请手动复制')
        })
    },
    exportDeepseekResult() {
      if (!this.deepseekResult) return
      const blob = new Blob([this.deepseekResult], { type: 'text/plain;charset=utf-8' })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = '智能分析.txt'
      document.body.appendChild(a)
      a.click()
      setTimeout(() => {
        document.body.removeChild(a)
        URL.revokeObjectURL(url)
      }, 100)
    },
    toggleMindmapNode(node) {
      this.$set(node, '_collapsed', !node._collapsed);
    },
    selectMindmapNode(node) {
      this.activeMindmapNode = node;
    },

    async generateAIMindmap() {
      console.log('policy.context:', this.policy.context);
      this.aiMindmapLoading = true;
      try {
        const resp = await fetch('/api/ai/policy/mindmap', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            text: this.policy.context,
            policyId: this.policy.id,
            dimension: this.mindmapDimension // 适配多维度
          })
        });
        const result = await resp.json();
        console.log('AI脑图接口完整返回:', result);
        function normalizeMindmapNode(node) {
          if (!node || typeof node !== 'object') return;
          if (!Array.isArray(node.children)) node.children = [];
          node.children = node.children.map(child => {
            if (typeof child === 'string') {
              return { title: child, children: [] };
            }
            normalizeMindmapNode(child);
            return child;
          });
        }
        normalizeMindmapNode(result.mindmap);
        
        // 前端额外优化：简化脑图结构
        if (result.mindmap) {
          this.optimizeMindmapDisplay(result.mindmap);
        }
        
        if (result && result.success && result.mindmap && result.mindmap.title) {
          this.policyMindmap = JSON.parse(JSON.stringify(result.mindmap));
          console.log('赋值后 policyMindmap.title:', this.policyMindmap.title);
          console.log('赋值后 policyMindmap.children:', this.policyMindmap.children);
        } else {
          this.policyMindmap = { title: '', children: [] };
          this.$toast?.error?.('AI生成失败') || alert('AI生成失败');
        }
      } catch (e) {
        this.policyMindmap = { title: '', children: [] };
        this.$toast?.error?.('AI生成异常') || alert('AI生成异常');
      } finally {
        this.aiMindmapLoading = false;
      }
    },
    changeMindmapDimension(dim) {
      this.mindmapDimension = dim;
      this.generateAIMindmap();
    },
    async generatePolicyFlowchart() {
      this.flowchartLoading = true;
      this.flowchartError = '';
      try {
        const resp = await fetch('/api/ai/policy/flowchart', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ text: this.policy.context, policyId: this.policy.id })
        });
        const result = await resp.json();

        // 调试输出后端返回内容
        console.log('后端返回流程图接口内容:', result);

        // 优先用 parsedJson 或 flowchart_json 字符串
        let flowchartJsonStr = result.parsedJson || result.flowchart_json;
        let flowchartObj = null;
        if (flowchartJsonStr && typeof flowchartJsonStr === 'string') {
          try {
            flowchartObj = JSON.parse(flowchartJsonStr);
            // 调试输出解析后的对象
            console.log('解析后的 flowchartObj:', flowchartObj);
          } catch (e) {
            this.flowchartError = '流程图JSON解析失败';
            this.flowchartData = null;
            return;
          }
        } else if (result.flowchart && typeof result.flowchart === 'object') {
          flowchartObj = result.flowchart;
          // 调试输出对象
          console.log('直接取 result.flowchart:', flowchartObj);
        }
        // 校验结构
        if (
          flowchartObj &&
          Array.isArray(flowchartObj.nodes) &&
          Array.isArray(flowchartObj.links)
        ) {
          this.flowchartRaw = JSON.stringify(flowchartObj); // 只用字符串
          this.renderFlowchart();
        } else {
          this.flowchartError = '流程图数据结构异常';
          this.flowchartData = null;
        }
        this.flowchartRaw = flowchartJsonStr || JSON.stringify(flowchartObj, null, 2) || '';
      } catch (e) {
        this.flowchartError = e.message || 'AI生成异常';
        this.flowchartData = null;
      } finally {
        this.flowchartLoading = false;
      }
    },
    renderFlowchart() {
      this.$nextTick(() => {
        const container = this.$refs.flowchart;
        if (!container) return;
        container.innerHTML = '';

        let nodes = [];
        let links = [];
        try {
          const raw = JSON.parse(this.flowchartRaw);
          nodes = Array.isArray(raw.nodes) ? raw.nodes : [];
          links = Array.isArray(raw.links) ? raw.links : [];
        } catch (e) {
          container.innerHTML = '<div style="color:#fca5a5;text-align:center;padding:32px 0;">流程图数据解析异常</div>';
          return;
        }

        const cyElements = [
          ...nodes.map(n => ({
            data: { id: n.id, label: n.name, type: n.type }
          })),
          ...links.map(l => ({
            data: { source: l.source, target: l.target, label: l.label }
          }))
        ];

        if (!nodes.length) {
          container.innerHTML = '<div style="color:#fca5a5;text-align:center;padding:32px 0;">暂无可展示的流程图数据</div>';
          return;
        }

        cytoscape({
          container,
          elements: cyElements,
          style: [
            {
              selector: 'node',
              style: {
                'background-color': '#00f5ff',
                'label': 'data(label)',
                'color': '#222',
                'font-size': '18px',         // 字体更大
                'text-valign': 'center',
                'text-halign': 'center',
                'width': 160,                // 节点更宽
                'height': 70,                // 节点更高
                'border-width': 3,
                'border-color': '#fff',
                'shape': 'roundrectangle',
                'text-wrap': 'wrap',
                'text-max-width': 140        // 文字自动换行
              }
            },
            {
              selector: 'edge',
              style: {
                'width': 3,
                'line-color': '#00f5ff',
                'target-arrow-color': '#00f5ff',
                'target-arrow-shape': 'triangle',
                'curve-style': 'bezier',
                'label': 'data(label)',
                'font-size': '14px',
                'color': '#fff',
                'text-background-color': '#222',
                'text-background-opacity': 0.7,
                'text-background-padding': 4
              }
            }
          ],
          layout: {
            name: 'dagre',
            rankDir: 'LR',
            nodeSep: 120,     // 节点间距更大
            edgeSep: 60,
            rankSep: 160
          }
        });
      });
    },
    generatePolicyMindmap(policy) {
      if (!policy || !policy.title) return { title: '', children: [] };
      // 简单静态结构，后续可AI生成
      return {
        title: policy.title,
        children: [
          {
            title: '基本信息', children: [
              { title: '发文编号：' + (policy.symbol || '-') },
              { title: '发布部门：' + (policy.department || '-') },
              { title: '发布时间：' + (policy.publish_date || '-') },
              { title: '生效时间：' + (policy.start_time || '-') },
              { title: '失效时间：' + (policy.end_time || '-') },
              { title: '政策类型：' + (policy.type || '-') },
              { title: '适用地区：' + (policy.address_2 || policy.address_1 || '-') }
            ]
          },
          {
            title: '政策要点', children: [
              { title: (policy.summary || '暂无要点') }
            ]
          },
          {
            title: '原文结构', children: [
              { title: (policy.context ? policy.context.slice(0, 30) + '...' : '无原文') }
            ]
          }
        ]
      };
    },onPolicyTitleEnter(policy, event) {
      clearTimeout(this._policyWindowTimer)
      this._isPolicyWindowHover = false
      this._isPolicyTitleHover = true
      this._policyWindowTimer = setTimeout(() => {
        this.policyWindowData = policy
        // 计算弹窗位置（与PolicyQuery一致，可根据需要微调）
        const rect = event.target.getBoundingClientRect()
        const popupWidth = 420
        const popupHeight = 600
        const padding = 16
        let x = rect.left + window.scrollX
        let y = rect.bottom + window.scrollY + 8
        const viewportHeight = window.innerHeight
        if (y + popupHeight + padding > window.scrollY + viewportHeight) {
          x = window.scrollX + window.innerWidth * 0.6 - popupWidth / 2
          y = window.scrollY + window.innerHeight / 2 - popupHeight / 2
          if (x + popupWidth > window.scrollX + window.innerWidth - padding) {
            x = window.scrollX + window.innerWidth - popupWidth - padding
          }
          if (x < window.scrollX + padding) {
            x = window.scrollX + padding
          }
          if (y < window.scrollY + padding) {
            y = window.scrollY + padding
          }
        }
        this.policyWindowPosition = { x, y }
        this.showPolicyWindow = true
      }, 300)
    },
    onPolicyTitleLeave() {
      this._isPolicyTitleHover = false
      clearTimeout(this._policyWindowTimer)
      this._policyWindowTimer = setTimeout(() => {
        if (!this._isPolicyTitleHover && !this._isPolicyWindowHover) {
          this.showPolicyWindow = false
        }
      }, 300)
    },
    onPolicyWindowEnter() {
      clearTimeout(this._policyWindowTimer)
      this._isPolicyWindowHover = true
    },
    onPolicyWindowLeave() {
      this._isPolicyWindowHover = false
      clearTimeout(this._policyWindowTimer)
      this._policyWindowTimer = setTimeout(() => {
        if (!this._isPolicyTitleHover && !this._isPolicyWindowHover) {
          this.showPolicyWindow = false
        }
      }, 300)
    },
    handleGoDetail(id) {
      this.$router.push({ name: 'PolicyDetail', params: { id } })
    },
    // 全屏模式相关方法
    openFlowchartFullScreen() {
      console.log('打开流程图全屏模式');
      if (!this.flowchartRaw || this.flowchartError) {
        console.log('流程图数据不可用:', { flowchartRaw: !!this.flowchartRaw, flowchartError: this.flowchartError });
        this.$toast?.error?.('暂无可展示的流程图数据') || alert('暂无可展示的流程图数据');
        return;
      }
      
      try {
        // 解析流程图数据
        let flowchartData;
        try {
          flowchartData = JSON.parse(this.flowchartRaw);
        } catch (parseError) {
          console.error('流程图数据解析失败:', parseError);
          this.$toast?.error?.('流程图数据格式错误') || alert('流程图数据格式错误');
          return;
        }

        const nodes = Array.isArray(flowchartData.nodes) ? flowchartData.nodes : [];
        const links = Array.isArray(flowchartData.links) ? flowchartData.links : [];
        
        if (!nodes.length) {
          this.$toast?.error?.('暂无可展示的流程图数据') || alert('暂无可展示的流程图数据');
          return;
        }

        // 显示侧边滑出图表
        this.slideGraphType = 'flowchart';
        this.slideGraphData = { nodes, links };
        this.showSlideGraph = true;
        
      } catch (e) {
        console.error('流程图数据解析失败:', e);
        this.$toast?.error?.('流程图数据解析失败') || alert('流程图数据解析失败');
      }
    },
    openMindmapFullScreen() {
      console.log('打开结构图全屏模式');
      console.log('传递给SlideGraphModal的数据:', this.policyMindmap);
      if (!this.policyMindmap || !this.policyMindmap.title) {
        console.log('结构图数据不可用:', { policyMindmap: this.policyMindmap });
        this.$toast?.error?.('暂无可展示的结构图数据') || alert('暂无可展示的结构图数据');
        return;
      }
      
      try {
        // 显示侧边滑出图表，传递标准对象，避免Proxy
        this.slideGraphType = 'mindmap';
        this.slideGraphData = JSON.parse(JSON.stringify(this.policyMindmap));
        this.showSlideGraph = true;
      } catch (error) {
        console.error('结构图全屏模式设置失败:', error);
        this.$toast?.error?.('结构图显示失败') || alert('结构图显示失败');
      }
    },
    closeSlideGraph() {
      this.showSlideGraph = false;
      this.slideGraphType = '';
      this.slideGraphData = null;
    },
    getNodeColor(type) {
      const colors = {
        'start': '#4ade80',
        'process': '#06b6d4', 
        'decision': '#f59e0b',
        'end': '#ef4444',
        'default': '#8b5cf6'
      };
      return colors[type] || colors.default;
    },
    getMindmapNodeColor(level) {
      const colors = [
        '#00ffe7',  // 根节点：亮青色
        '#22d3ee',  // 一级节点：亮蓝色  
        '#06b6d4',  // 二级节点：中蓝色
        '#0891b2'   // 三级节点：深蓝色
      ];
      return colors[level] || colors[colors.length - 1];
    },
    
    // 优化脑图显示：简化节点文本，过滤冗余内容
    optimizeMindmapDisplay(node, level = 0) {
      if (!node || typeof node !== 'object') return;
      
      // 如果超过显示层级，直接清空子节点
      if (level >= this.mindmapShowLevel) {
        node.children = [];
        return;
      }
      
      // 优化节点标题
      if (node.title) {
        let title = node.title.toString();
        
        // 根据层级动态调整标题长度
        const maxLength = level === 0 ? 25 : (level === 1 ? 18 : (level === 2 ? 12 : 8));
        if (title.length > maxLength) {
          title = title.substring(0, maxLength) + '...';
        }
        
        // 移除冗余符号和格式
        if (this.mindmapSimplified) {
          title = title.replace(/[（）()【】\[\]]/g, '');
          title = title.replace(/第[一二三四五六七八九十\d]+[条章节]/g, '');
          title = title.replace(/^\d+[\.、]/g, '');
          title = title.replace(/\s+/g, ' '); // 合并多个空格
        }
        
        node.title = title.trim();
      }
      
      // 递归处理子节点
      if (Array.isArray(node.children)) {
        // 根据简化模式和层级限制显示的子节点数量
        const maxChildren = this.mindmapSimplified ? 
          (level === 0 ? 5 : (level === 1 ? 4 : 3)) : // 简化模式：5-4-3
          (level === 0 ? 6 : (level === 1 ? 5 : 4));  // 完整模式：6-5-4
          
        node.children = node.children.slice(0, maxChildren);
        
        node.children.forEach(child => {
          this.optimizeMindmapDisplay(child, level + 1);
        });
      }
    },
    
    // 切换脑图简化模式
    toggleMindmapSimplified() {
      this.mindmapSimplified = !this.mindmapSimplified;
      this.generateAIMindmap();
    },
    
    // 调整脑图显示层级
    adjustMindmapLevel(level) {
      this.mindmapShowLevel = level;
      this.generateAIMindmap();
    },
    
    // 重新加载政策详情
    async retryLoadPolicy() {
      const id = this.$route.params.id;
      if (!id) return;
      
      this.isLoading = true;
      try {
        await this.fetchPolicy(id);
      } catch (error) {
        console.error('重新加载失败:', error);
      } finally {
        this.isLoading = false;
      }
    },
    
    // 格式化日期的方法
    formatDate(dateStr) {
      if (!dateStr || dateStr === 'null' || dateStr === '') {
        return '-';
      }
      try {
        const date = new Date(dateStr);
        if (isNaN(date.getTime())) {
          return dateStr; // 如果不是有效日期，返回原字符串
        }
        return date.toLocaleDateString('zh-CN');
      } catch (error) {
        return dateStr;
      }
    }
  },
  mounted() {
    // 监听sidebar折叠事件，动态调整宽度
    this._sidebarCollapseHandler = (e) => {
      if (e && e.detail && typeof e.detail.collapsed === 'boolean') {
        this.sidebarCollapsed = e.detail.collapsed;
      } else {
        this.sidebarCollapsed = !!window.sidebarCollapsed;
      }
    };
    window.addEventListener('sidebar-collapse', this._sidebarCollapseHandler);
    // 初始化
    this.sidebarCollapsed = !!window.sidebarCollapsed;
  },
  beforeUnmount() {
    window.removeEventListener('sidebar-collapse', this._sidebarCollapseHandler);
  }
}
</script>

<style scoped>
:deep() {
  user-select: text;
  -webkit-user-select: text;
  caret-color: transparent;
}
</style>
<style>
/* 浅色模式下政策原文内容字体适配 */
.theme-light pre.text-white\/90,
.theme-light pre.text-white,
.theme-light pre {
  color: #222 !important;
  background: #f7fafc !important;
  border-radius: 8px;
  padding: 1em;
  font-size: 1em;
  line-height: 1.8;
  box-shadow: 0 2px 12px #e0e7ef22;
}
</style>
<style>
/* 浅色模式下政策详情页高对比度适配 */
.theme-light .text-white,
.theme-light .text-white\/70,
.theme-light .text-white\/80,
.theme-light .text-white\/50 {
  color: #222 !important;
}
.theme-light .bg-white\/5 {
  background: #fff !important;
  color: #222 !important;
  border: 1px solid #e0e7ef !important;
  box-shadow: 0 4px 24px #e0e7ef33 !important;
}
.theme-light .border-white\/10 {
  border-color: #e0e7ef !important;
}
.theme-light .text-electric-400 {
  color: #0073e6 !important;
}
.theme-light .text-electric-500 {
  color: #00b8d9 !important;
}
.theme-light .bg-electric-500 {
  background: #e0f7fa !important;
  color: #007a8a !important;
}
.theme-light .bg-electric-400 {
  background: #b2ebf2 !important;
  color: #007a8a !important;
}
.theme-light .hover\:bg-electric-400:hover {
  background: #b2ebf2 !important;
  color: #007a8a !important;
}
.theme-light .rounded-md,
.theme-light .rounded-lg,
.theme-light .rounded {
  border-radius: 8px !important;
}
.theme-light .shadow,
.theme-light .shadow-md {
  box-shadow: 0 4px 24px #e0e7ef33 !important;
}
.theme-light .text-black {
  color: #222 !important;
}
.theme-light .text-blue-400 {
  color: #0073e6 !important;
}
.theme-light .bg-blue-500\/20 {
  background: #e6f7ff !important;
  color: #0073e6 !important;
}
.theme-light .bg-green-500\/20 {
  background: #e6ffed !important;
  color: #22c55e !important;
}
.theme-light .text-green-400 {
  color: #22c55e !important;
}
.theme-light .bg-yellow-500\/20 {
  background: #fffbe6 !important;
  color: #b58105 !important;
}
.theme-light .text-yellow-400 {
  color: #eab308 !important;
}
.theme-light .bg-black\/10 {
  background: #f7fafc !important;
  color: #222 !important;
}
.theme-light .hover\:bg-white\/10:hover {
  background: #e6f7ff !important;
  color: #0073e6 !important;
}
.theme-light .text-cyber-50 {
  color: #fff !important;
}
.theme-light .text-red-400 {
  color: #ef4444 !important;
}
.theme-light .bg-gray-900 {
  background: #f7fafc !important;
  color: #222 !important;
}
</style>

<style scoped>
:deep() {
  user-select: text;
  -webkit-user-select: text;
  caret-color: transparent;
  cursor: default;
}

:deep(button) {
  cursor: pointer;
}

:deep(.policy-content) {
  ::selection {
    color: inherit;
  }
}

.policy-column {
  max-height: 300px;
  overflow-y: auto;
  background: #111;
  padding: 8px;
  border-radius: 6px;
}

.policy-item {
  padding: 0.75rem;
  border-radius: 0.5rem;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: all 0.3s ease;
  background-color: rgba(55, 65, 81, 1);
  /* bg-gray-700 */

  /* 伪元素实现边框动画 */
  &::before {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    border-radius: 0.5rem;
    border-width: 2px;
    pointer-events: none;
    border-color: transparent;
    transition: all 0.3s ease;
    transform: scale(0.98);
    opacity: 0;
  }

  &:hover {
    background-color: rgba(55, 65, 81, 0.8);
    transform: translateY(-1px);
  }

  &.selected {
    opacity: 1;
    box-shadow: 0 0 10px rgba(0, 255, 255, 0.3);
  }
}


/* 添加内容动画 */
.policy-item p {
  transition: transform 0.2s ease;
}

.policy-item:hover p {
  transform: translateX(2px);
}
.my-element {
  background-color: var(--color-primary);
  color: var(--color-textPrimary);
  border: 1px solid var(--color-border);
}
</style>
